package org.grc.app.z_project.z_framework.proxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import net.sf.cglib.proxy.MethodProxy;

/*
 * 所谓代理链模式，就是可以将多个代理通过一个链子串起来，一个个地执行，
 * 执行先后顺序取决于添加到链上的先后顺序。
 */

/**
 * 代理链
 * 
 * @author grc
 * @since 1.0-SNAPSHOT
 */
public class ProxyChain {

	// 目标类
	private final Class<?> targetClass;
	// 目标对象
	private final Object targetObject;
	// 目标方法
	private final Method targetMethod;
	// 方法代理
	private final MethodProxy methodProxy;
	// 方法参数
	private final Object[] methodParams;
	
	// 代理列表
	private List<Proxy> proxyList = new ArrayList<Proxy>();
	// 代理索引
	private int proxyIndex = 0;
	
	public ProxyChain (Class<?> targetClass, Object targetObject,
			Method targetMethod, MethodProxy methodProxy, Object[] methodParams, 
			List<Proxy> proxyList) {
		this.targetClass = targetClass;
		this.targetObject = targetObject;
		this.targetMethod = targetMethod;
		this.methodProxy = methodProxy;
		this.methodParams = methodParams;
		this.proxyList = proxyList;
	}
	
	// 通过 proxyIndex来作为代理对象的计数器，尚若未达到 proxyList的上限，
	// 则从相应的 proxyList取出相应的 Proxy对象，并调用其 doProxy方法。
	//
	// 在 Proxy接口的实现中会提供相应的横切逻辑，并调用 doProxyChain方法，
	// 随时将再次调用当前 ProxyChain对象的 doProxyChain方法，直到 proxyIndex
	// 达到 proxyList的上限，最后调用 methodProxy的 invokeSuper方法，执行
	// 目标对象的业务逻辑。
	public Object doProxyChain () throws Throwable {
		Object methodResult = null;
		if (proxyIndex < proxyList.size()) {
			// this指向是代理链的关键
			methodResult = proxyList.get(proxyIndex++).doProxy(this);
		} else {
			methodResult = methodProxy.invokeSuper(targetObject, methodParams);
		}
		return methodResult;
	}
	
	public Object[] getMethodParams () {
		return this.methodParams;
	}

	public Class<?> getTargetClass() {
		return targetClass;
	}

	public Method getTargetMethod() {
		return targetMethod;
	}
}
